package com.bjpowernode.config.filter;

import com.bjpowernode.constant.Constants;
import com.bjpowernode.model.TUser;
import com.bjpowernode.result.R;
import com.bjpowernode.service.RedisService;
import com.bjpowernode.util.JSONUtil;
import com.bjpowernode.util.JWTUtil;
import com.bjpowernode.util.ResponseUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 验证jwt的Filter
 */
@Component
public class VerifyJwtFilter extends OncePerRequestFilter {

    @Resource
    private RedisService redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //验证jwt对不对？ 登录时还没有生成jwt，所以登录的请求要放行，不要拦截
        if (request.getRequestURI().equals(Constants.LOGIN_URI)) {
            filterChain.doFilter(request, response);
        } else {
            //拿到请求头中的jwt
            String jwt = request.getHeader("Authorization");
                //如果是导出Excel的请求，则从地址栏参数中获取一下jwt
            if (Constants.EXPORT_EXCEL_URI.equals(request.getRequestURI())) {
                jwt = request.getParameter("Authorization");
            }
            //1、验证是否为空
            if (!StringUtils.hasText(jwt)) {
                //返回JSON出去
                R result = new R(901,"jwt参数为空", null);
                //把result对象转成JSON
                String json = JSONUtil.toJSON(result);
                //结果写出去
                ResponseUtil.write(response, json);
                return;
            }

            //2、验证jwt有没有被篡改过
            if (!JWTUtil.verifyJWT(jwt)) {
                //返回JSON出去
                R result = new R(902,"jwt参数不合法", null);
                //把result对象转成JSON
                String json = JSONUtil.toJSON(result);
                //结果写出去
                ResponseUtil.write(response, json);
                return;
            }

            //3、验证jwt和redis中的jwt是否匹配
            String loginUserJSON = JWTUtil.parseJWT(jwt);
            TUser tUser = JSONUtil.toBean(loginUserJSON, TUser.class);

            String redisJWT = (String)redisService.getValue(Constants.REDIS_LOGIN_JWT_KEY + tUser.getId());
            if (!jwt.equals(redisJWT)) {
                //返回JSON出去
                R result = new R(903,"jwt参数不匹配", null);
                //把result对象转成JSON
                String json = JSONUtil.toJSON(result);
                //结果写出去
                ResponseUtil.write(response, json);
                return;
            }

            //设置jwt的过期时间，如果选择了记住我，过期时间是7天，否则是30分钟
            String rememberMe = request.getHeader("rememberMe");
            if (Boolean.parseBoolean(rememberMe)) {
                redisService.expire(Constants.REDIS_LOGIN_JWT_KEY + tUser.getId(), Constants.EXPIRE_TIME, TimeUnit.MINUTES);
            } else {
                redisService.expire(Constants.REDIS_LOGIN_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.MINUTES);
            }

            //以上验证通过了，你要告诉spring security，这个jwt是登录过了，你让他正常访问接口
            //回填数据到SecurityContextHolder.content
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser, tUser.getPassword(), tUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            //以上的验证如果都通过了，那么可以继续执行下一个过滤器
            filterChain.doFilter(request, response);
        }
    }
}
